#ifndef APP_ALGORITHM_SORTING_ALGORITHM_INCLUDE_SORTING_ALGORITHM_H
#define APP_ALGORITHM_SORTING_ALGORITHM_INCLUDE_SORTING_ALGORITHM_H

#include <iostream>
#include <vector>

class ISortingAlgorithm {
public:
    virtual ~ISortingAlgorithm() = default;
    virtual std::vector<int32_t> Executor(const std::vector<int32_t> &data);

protected:
    explicit ISortingAlgorithm(const char* desc) : descriptor_(desc) {}
    const char* Descriptor() const {
        return descriptor_;
    }

private:
    virtual void Sort(std::vector<int32_t> &data) = 0;

    const char* descriptor_ = "ISortingAlgorithm";
    std::vector<int32_t> data_;
};

class BubbleSort : public ISortingAlgorithm {
public:
    BubbleSort() : ISortingAlgorithm("BubbleSort") {}
    ~BubbleSort() override = default;
private:
    void Sort(std::vector<int32_t> &data) override;
};

class InsertionSort : public ISortingAlgorithm {
public:
    InsertionSort() : ISortingAlgorithm("InsertionSort") {}
    ~InsertionSort() override = default;
private:
    void Sort(std::vector<int32_t> &data) override;
};

class QuickSort : public ISortingAlgorithm {
public:
    QuickSort() : ISortingAlgorithm("QuickSort") {}
    ~QuickSort() override = default;
private:
    void Sort(std::vector<int32_t> &data) override;
    std::ptrdiff_t Partition(std::vector<int32_t> &data, std::ptrdiff_t low, std::ptrdiff_t high);
    void QuickSortRecursive(std::vector<int32_t> &data, std::ptrdiff_t low, std::ptrdiff_t high);
};

class MergeSort : public ISortingAlgorithm {
public:
    MergeSort() : ISortingAlgorithm("MergeSort") {}
    ~MergeSort() override = default;
private:
    void Sort(std::vector<int32_t> &data) override;
    void Merge(std::vector<int32_t> &data, std::ptrdiff_t left, std::ptrdiff_t mid, std::ptrdiff_t right);
    void MergeSortRecursive(std::vector<int32_t> &data, std::ptrdiff_t left, std::ptrdiff_t right);
};

class HeapifySort : public ISortingAlgorithm {
public:
    HeapifySort() : ISortingAlgorithm("HeapifySort") {}
    ~HeapifySort() override = default;
private:
    void Sort(std::vector<int32_t> &data) override;
    void Heapify(std::vector<int32_t> &data, std::ptrdiff_t n, std::ptrdiff_t i);
};

#endif // APP_ALGORITHM_SORTING_ALGORITHM_INCLUDE_SORTING_ALGORITHM_H